/**
 * Token管理工具类
 * 提供Token的解析、验证、过期检查等功能
 */

// Token载荷接口
interface TokenPayload {
  sub?: string;        // 用户ID
  username?: string;   // 用户名
  role?: string;       // 用户角色
  iat?: number;        // 签发时间
  exp?: number;        // 过期时间
  [key: string]: string | number | boolean | undefined;  // 其他自定义字段
}

// Token信息接口
interface TokenInfo {
  payload: TokenPayload;
  isValid: boolean;
  isExpired: boolean;
  expiresAt: Date | null;
  timeToExpire: number; // 距离过期的毫秒数
}

class TokenManager {
  private static readonly TOKEN_KEY = 'token';
  private static readonly REFRESH_TOKEN_KEY = 'refreshToken';
  
  /**
   * 解析JWT Token
   * @param token JWT Token字符串
   * @returns Token载荷信息
   */
  static parseToken(token: string): TokenPayload | null {
    try {
      // JWT格式：header.payload.signature
      const parts = token.split('.');
      if (parts.length !== 3) {
        return null;
      }

      // 解码payload部分（Base64URL）
      const payload = parts[1];
      const decoded = atob(payload.replace(/-/g, '+').replace(/_/g, '/'));
      return JSON.parse(decoded);
    } catch (error) {
      console.error('解析Token失败:', error);
      return null;
    }
  }

  /**
   * 检查Token是否过期
   * @param token JWT Token字符串
   * @returns 是否过期
   */
  static isTokenExpired(token: string): boolean {
    const payload = this.parseToken(token);
    if (!payload || !payload.exp) {
      return true;
    }

    // exp是秒级时间戳，需要转换为毫秒
    const expirationTime = payload.exp * 1000;
    const currentTime = Date.now();
    
    return currentTime >= expirationTime;
  }

  /**
   * 获取Token过期时间
   * @param token JWT Token字符串
   * @returns 过期时间Date对象，如果无法解析则返回null
   */
  static getTokenExpiration(token: string): Date | null {
    const payload = this.parseToken(token);
    if (!payload || !payload.exp) {
      return null;
    }

    return new Date(payload.exp * 1000);
  }

  /**
   * 获取Token剩余有效时间（毫秒）
   * @param token JWT Token字符串
   * @returns 剩余有效时间，如果已过期或无法解析则返回0
   */
  static getTimeToExpire(token: string): number {
    const expirationTime = this.getTokenExpiration(token);
    if (!expirationTime) {
      return 0;
    }

    const timeToExpire = expirationTime.getTime() - Date.now();
    return Math.max(0, timeToExpire);
  }

  /**
   * 检查Token是否即将过期（默认5分钟内）
   * @param token JWT Token字符串
   * @param thresholdMinutes 阈值分钟数，默认5分钟
   * @returns 是否即将过期
   */
  static isTokenExpiringSoon(token: string, thresholdMinutes: number = 5): boolean {
    const timeToExpire = this.getTimeToExpire(token);
    const thresholdMs = thresholdMinutes * 60 * 1000;
    
    return timeToExpire > 0 && timeToExpire <= thresholdMs;
  }

  /**
   * 获取完整的Token信息
   * @param token JWT Token字符串
   * @returns Token信息对象
   */
  static getTokenInfo(token: string): TokenInfo {
    const payload = this.parseToken(token);
    const isExpired = this.isTokenExpired(token);
    const expiresAt = this.getTokenExpiration(token);
    const timeToExpire = this.getTimeToExpire(token);

    return {
      payload: payload || {},
      isValid: !!payload,
      isExpired,
      expiresAt,
      timeToExpire
    };
  }

  /**
   * 获取当前存储的Token信息
   * @returns 当前Token信息，如果没有Token则返回null
   */
  static getCurrentTokenInfo(): TokenInfo | null {
    const token = localStorage.getItem(this.TOKEN_KEY);
    if (!token) {
      return null;
    }

    return this.getTokenInfo(token);
  }

  /**
   * 检查当前用户是否已认证且Token有效
   * @returns 是否已认证
   */
  static isAuthenticated(): boolean {
    const token = localStorage.getItem(this.TOKEN_KEY);
    const refreshToken = localStorage.getItem(this.REFRESH_TOKEN_KEY);
    
    if (!token || !refreshToken) {
      return false;
    }

    return !this.isTokenExpired(token);
  }

  /**
   * 获取当前用户信息
   * @returns 用户信息，如果未登录则返回null
   */
  static getCurrentUser(): TokenPayload | null {
    const tokenInfo = this.getCurrentTokenInfo();
    return tokenInfo?.payload || null;
  }

  /**
   * 清除所有Token信息
   */
  static clearTokens(): void {
    localStorage.removeItem(this.TOKEN_KEY);
    localStorage.removeItem(this.REFRESH_TOKEN_KEY);
  }

  /**
   * 设置Token信息
   * @param token 访问Token
   * @param refreshToken 刷新Token
   */
  static setTokens(token: string, refreshToken: string): void {
    localStorage.setItem(this.TOKEN_KEY, token);
    localStorage.setItem(this.REFRESH_TOKEN_KEY, refreshToken);
  }

  /**
   * 获取当前访问Token
   * @returns 当前访问Token，如果没有则返回null
   */
  static getToken(): string | null {
    return localStorage.getItem(this.TOKEN_KEY);
  }

  /**
   * 获取当前刷新Token
   * @returns 当前刷新Token，如果没有则返回null
   */
  static getRefreshToken(): string | null {
    return localStorage.getItem(this.REFRESH_TOKEN_KEY);
  }

  /**
   * 获取格式化的Token过期时间字符串
   * @param token JWT Token字符串
   * @returns 格式化的过期时间字符串
   */
  static getFormattedExpiration(token: string): string {
    const expirationTime = this.getTokenExpiration(token);
    if (!expirationTime) {
      return '无法解析过期时间';
    }

    return expirationTime.toLocaleString('zh-CN', {
      year: 'numeric',
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit',
      second: '2-digit'
    });
  }

  /**
   * 获取Token剩余时间的友好显示
   * @param token JWT Token字符串
   * @returns 友好的剩余时间显示
   */
  static getTimeToExpireDisplay(token: string): string {
    const timeToExpire = this.getTimeToExpire(token);
    
    if (timeToExpire <= 0) {
      return '已过期';
    }

    const minutes = Math.floor(timeToExpire / (1000 * 60));
    const hours = Math.floor(minutes / 60);
    const days = Math.floor(hours / 24);

    if (days > 0) {
      return `${days}天${hours % 24}小时`;
    } else if (hours > 0) {
      return `${hours}小时${minutes % 60}分钟`;
    } else {
      return `${minutes}分钟`;
    }
  }
}

export default TokenManager;
export type { TokenPayload, TokenInfo }; 